package com.dayu.gulimall.product;

import org.mybatis.spring.annotation.MapperScan;
import org.redisson.spring.session.config.EnableRedissonHttpSession;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
 * 1引入jar包 mybatis-plus,mysql-connector-java驱动包
 * 2、 设置mapperScan位置
 * 3、配置yml
 * <p>
 * 高并发下缓存失效的问题:
 * 1、缓存穿透
 * 指查询一个不存在的数据，缓存不命中，则取数据库中查找数据，但是数据库中也没有这个值，我们没有将这次查询到null值保存在缓存中。
 * 这个将导致不存在的数据都要到数据库中查找，就失去了缓存的意义。----》 瞬时压力过大，导致的数据库崩溃。
 * 解决办法： 将null结果缓存，并加入短暂的过期时间
 * 2、缓存雪崩
 * 大面积key同时失效，请求全部转到db。db的瞬时压力过大。
 * 解决办法： 原有的过期时间的基础上增加一个随机值。比如1~5分钟时间，这样每一个缓存的过期时间重复率就会降低，很难引发集体失效的事件。
 * 3、缓存击穿
 * 指的是某一个高频访问的key，（热点key）在大量请求的时候刚好失效了，这个key的数据查询全部转到db
 * 解决办法： 加锁
 * 大量的并发只让一个查询，其他线程等待。查到了以后再释放锁。其他线程获取到锁之后先查缓存就会有数据，就不会击穿。
 *
 *
 * 二:redission  操作redlock，redis的分布式锁操作
 *  2.1) 引入依赖:
 *        <dependency>
 *             <groupId>org.redisson</groupId>
 *             <artifactId>redisson</artifactId>
 *             <version>3.14.0</version>
 *         </dependency>
 *  2.2) 写配置
 *  配置方法有很多种，这里写configration
 *
 *
 * 给缓存中存放json字符串，拿出的json字符串还可以转成对象类型（序列化和反序列化）
 *
 *
 *  缓存数据一致性-解决方案
 * ·无论是双写模式还是失效模式，都会导致缓存的不一致问题。即多个实例同时更新会出事。怎么办?
 * ·1、如果是用户纬度数据（订单数据、用户数据），这种并发几率非常小，不用考虑这个问题，缓存数据加上过期时间，每隔―段时间触发读的主动更新即可
 * ·2、如果是菜单，商品介绍等基础数据，也可以去使用canal订阅binlog的方式。
 * .3、缓存数据+过期时间也足够解决大部分业务对于缓存的要求。
 * ·4、通过加锁保证并发读写，写写的时候按顺序排好队。读读无所谓。所以适合使用读写锁。(业务不关心脏数据，允许临时脏数据可忽略)
 * ·总结:
 * ·我们能放入缓存的数据本就不应该是实时性、一致性要求超高的。所以缓存数据的时候加上过期时间，保证每天拿到当前最新数据即可。
 * ·我们不应该过度设计，增加系统的复杂性
 * .遇到实时性、一致性要求高的数据，就应该查数据库，即使慢点。
 *
 * 我们系统的一致性解决方案:
 * 1、缓存的所有数据都有过期时间，数据过期下一次查询触发主动更新
 * 2、读写数据的时候，加上分布式的读写锁.经常写，经常读
 *
 *
 * 三：整合springCache简化缓存开发
 *      1、引入依赖
 *          spring-boot-starter-cache   、spring-boot-starter-data-redis
 *       2、写配置
 *          1、自动配置了哪些
 *          CacheAutoConfiguration、RedisCacheConfiguration自动配置好了缓存管理器RedisCacheManager
 *          2) 配置文件配置使用redis作为缓存
 *          spring.cache.type=redis
 *       3、、测试使用缓存
 *          @Cacheable : Triggers cache population.:触发将数据保存到缓存的操作CacheEvict:Triggers cache eviction.:触发将数据从缓存删除的操作
 *          @CachePut :  Updates the cache without interfering with the method execution.:不影响方法执行更新缓存
 *          @Caching : Regroups multiple cache operations to be appLied on a method.组合以上多个操作
 *          @CacheConfig : Shares some common cache-reLated stettings at class-Level.:在类级别共享缓存的相同配置
 *
 *
 *
 *
 *
 */

//@EnableCaching  //使用缓存，放到Cache配置类中
@EnableRedisHttpSession
@EnableFeignClients(basePackages = "com.dayu.gulimall.product.feign")
@EnableDiscoveryClient
@MapperScan("com.dayu.gulimall.product.dao")
@SpringBootApplication
public class GulimallProductApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallProductApplication.class, args);
    }

}
